#ifndef __CAPAINDICES_ARBOLBMAS_CONDICIONES_CPP_
#define __CAPAINDICES_ARBOLBMAS_CONDICIONES_CPP_

/*****************************************************************************
*                     Organizaci�n de Datos - 75.06                          *
*                         C�tedra Lic. Servetto                              *
*            Facultad de Ingenier�a - Universidad de Buenos Aires            *
******************************************************************************/

#include "Condiciones.h"

#include <iostream>

using namespace std;
using namespace Comun;

namespace Comun
{
	

	CondicionMayor::CondicionMayor(){
		this->Simbolo =Mayor;
	}

	CondicionMayorIgual::CondicionMayorIgual(){
		this->Simbolo =MayorIgual;
	}

	CondicionIgual::CondicionIgual(){
		this->Simbolo =Igual;
	}

	CondicionMenor::CondicionMenor(){
		this->Simbolo =Menor;
	}

	CondicionMenorIgual::CondicionMenorIgual(){
		this->Simbolo =MenorIgual;
	}

	bool CondicionMenor::Analizar(list<Atributo> atributos, list<string> valores){

		typedef list<string>::iterator IteradorDeValores;
		IteradorDeValores IV = valores.begin();

		bool ultimoIgual;

		for ( IteradorDeAtributos i = atributos.begin(); i != atributos.end(); i++){
			Atributo a  = *i;
			// Verifica que el valor no sea nulo, lo cual indica
			// que no se quiere operar sobre el
			if ((*IV).compare("") != 0)
				if (!esMenor(a.Tipo,a.Valor,*IV))
				{
					if (!esIgual(a.Tipo,a.Valor,*IV))					
						return false;
					else
						ultimoIgual = true;
				}
				else
					{
					ultimoIgual = false;
					break;
				}
			IV++;
		}

		return !ultimoIgual;

	}

	bool CondicionMenor::Analizar(Registro registro){

		for ( IteradorDeAtributos i = registro.Atributos.begin(); i != registro.Atributos.end(); i++)
		{
			Atributo a  = *i;
			if ( (a.Nombre.compare(ValorCondicion.Nombre) == 0) && ( a.Tipo == a.Tipo))
				if (!esMenor(a.Tipo,a.Valor,ValorCondicion.Valor))
					return false;
		}

		return true;

	}

	bool CondicionMenor::esMenor(TipoRegistro tipo, string valor1, string valor2){
		short s1, s2, anio1=0, mes1=0, dia1=0, anio2=0, mes2=0, dia2=0;
		int i1, i2;
		float f1, f2;

		switch(tipo)
		{
		case Booleano:
			return valor1.compare(0,1,valor2) != 0;

		case Cadena:
			return valor1.compare(valor2) < 0;

		case Caracter:
			return valor1.compare(0,1,valor2) < 0;

		case Entero:
			s1 = (short) atoi(valor1.c_str());
			s2 = (short) atoi(valor2.c_str());

			return s1 < s2;

		case EnteroLargo:
			i1 = atoi(valor1.c_str());
			i2 = atoi(valor2.c_str());

			return i1 < i2;

			break;
		case Fecha:
			if (valor1!=""){
			anio1 = (short) atoi(valor1.substr(6,4).c_str());
			mes1 = (short) atoi(valor1.substr(3,2).c_str());
			dia1 = (short) atoi(valor1.substr(0,2).c_str());
			}
			if (valor2!=""){
			anio2 = (short) atoi(valor2.substr(6,4).c_str());
			mes2= (short) atoi(valor2.substr(3,2).c_str());
			dia2 = (short) atoi(valor2.substr(0,2).c_str());
			}
			if (anio1<anio2)
				return true;
			else if (anio1 == anio2)
			{
				if (mes1<mes2)
					return true;
				else if ( (mes1== mes2) && (dia1<dia2) )
					return true;
			}

			return false;

		case Real:
			f1 = (float) atof(valor1.c_str());
			f2 = (float) atof(valor2.c_str());

			return f1<f2;
		default:
			cerr << "CapaIndices->Condiciones.cpp->CondicionMenor::esMenor(TipoRegistro tipo, string valor1, string valor2)" << endl << "Invalido." << endl;
			throw new exception();
		}
	}

	bool CondicionMenorIgual::Analizar(list<Atributo> atributos, list<string> valores){

		typedef list<string>::iterator IteradorDeValores;
		IteradorDeValores IV = valores.begin();

		for ( IteradorDeAtributos i = atributos.begin(); i != atributos.end(); i++){
			Atributo a  = *i;
			// Verifica que el valor no sea nulo, lo cual indica
			// que no se quiere operar sobre el
			if ((*IV).compare("") != 0)
				if (!esMenorIgual(a.Tipo,a.Valor,*IV))
					return false;

			IV++;
		}

		return true;

	}

	bool CondicionMenorIgual::Analizar(Registro registro){

		for ( IteradorDeAtributos i = registro.Atributos.begin(); i != registro.Atributos.end(); i++)
		{
			Atributo a  = *i;
			if ( (a.Nombre.compare(ValorCondicion.Nombre) == 0) && ( a.Tipo == a.Tipo))
				if (!esMenorIgual(a.Tipo,a.Valor,ValorCondicion.Valor))
					return false;		
		}

		return true;

	}


	bool CondicionMenorIgual::esMenorIgual(TipoRegistro tipo, string valor1, string valor2){
		short s1, s2, anio1, mes1, dia1, anio2, mes2, dia2;
		int i1, i2;
		float f1, f2;

		switch(tipo)
		{
		case Booleano:
			return valor1.compare(0,1,valor2) <= 0;

		case Cadena:
			return valor1.compare(valor2) <= 0;

		case Caracter:
			return valor1.compare(0,1,valor2) <= 0;

		case Entero:
			s1 = (short) atoi(valor1.c_str());
			s2 = (short) atoi(valor2.c_str());

			return s1 <= s2;

		case EnteroLargo:
			i1 = atoi(valor1.c_str());
			i2 = atoi(valor2.c_str());

			return i1 <= i2;

			break;
		case Fecha:
			anio1 = (short) atoi(valor1.substr(6,4).c_str());
			mes1 = (short) atoi(valor1.substr(3,2).c_str());
			dia1 = (short) atoi(valor1.substr(0,2).c_str());

			anio2 = (short) atoi(valor2.substr(6,4).c_str());
			mes2= (short) atoi(valor2.substr(3,2).c_str());
			dia2 = (short) atoi(valor2.substr(0,2).c_str());

			if (anio1<anio2)
				return true;
			else if (anio1 == anio2)
			{
				if (mes1<mes2)
					return true;
				else if ( (mes1== mes2) && (dia1 <= dia2) )
					return true;
			}

			return false;

		case Real:
			f1 = (float) atof(valor1.c_str());
			f2 = (float) atof(valor2.c_str());

			return f1<f2;
		default:
			cerr << "CapaIndices->Condiciones.cpp->CondicionMenorIgual::esMenorIgual(TipoRegistro tipo, string valor1, string valor2)" << endl << "Invalido." << endl;
			throw new exception();
		}
	}

	bool CondicionMayor::Analizar(list<Atributo> atributos, list<string> valores){

		typedef list<string>::iterator IteradorDeValores;
		IteradorDeValores IV = valores.begin();

		bool ultimoIgual = false;

		for ( IteradorDeAtributos i = atributos.begin(); i != atributos.end(); i++){
			Atributo a  = *i;			
			// Verifica que el valor no sea nulo, lo cual indica
			// que no se quiere operar sobre el
			if ((*IV).compare("") != 0)
				if (!esMayor(a.Tipo,a.Valor,*IV))
				{
					if (!esIgual(a.Tipo,a.Valor,*IV))					
						return false;
					else
						ultimoIgual = true;
				}
				else
				{
					ultimoIgual = false;
					break;
				}
			IV++;
		}

		return !ultimoIgual;
	}

	bool CondicionMayor::Analizar(Registro registro){

		for ( IteradorDeAtributos i = registro.Atributos.begin(); i != registro.Atributos.end(); i++)
		{
			Atributo a  = *i;
			if ( (a.Nombre.compare(ValorCondicion.Nombre) == 0) && ( a.Tipo == a.Tipo))
				if (!esMayor(a.Tipo,a.Valor,ValorCondicion.Valor))
					return false;
				else if (!esIgual(a.Tipo,a.Valor,ValorCondicion.Valor))
					break;
		}

		return true;

	}

	bool CondicionMayor::esMayor(TipoRegistro tipo, string valor1, string valor2){
		short s1, s2, anio1, mes1, dia1, anio2, mes2, dia2;
		int i1, i2;
		float f1, f2;

		switch(tipo)
		{
		case Booleano:
			return valor1.compare(0,1,valor2) != 0;

		case Cadena:
			return valor1.compare(valor2) > 0;

		case Caracter:
			return valor1.compare(0,1,valor2) > 0;

		case Entero:
			s1 = (short) atoi(valor1.c_str());
			s2 = (short) atoi(valor2.c_str());

			return s1 > s2;

		case EnteroLargo:
			i1 = atoi(valor1.c_str());
			i2 = atoi(valor2.c_str());

			return i1 > i2;

			break;
		case Fecha:
			anio1 = (short) atoi(valor1.substr(6,4).c_str());
			mes1 = (short) atoi(valor1.substr(3,2).c_str());
			dia1 = (short) atoi(valor1.substr(0,2).c_str());

			anio2 = (short) atoi(valor2.substr(6,4).c_str());
			mes2= (short) atoi(valor2.substr(3,2).c_str());
			dia2 = (short) atoi(valor2.substr(0,2).c_str());

			if (anio1>anio2)
				return true;
			else if (anio1 == anio2)
			{
				if (mes1>mes2)
					return true;
				else if ( (mes1== mes2) && (dia1>dia2) )
					return true;
			}

			return false;

		case Real:
			f1 = (float) atof(valor1.c_str());
			f2 = (float) atof(valor2.c_str());

			return f1>f2;
		default:
			cerr << "CapaIndices->Condiciones.cpp->CondicionMayor::esMayor(TipoRegistro tipo, string valor1, string valor2)" << endl << "Invalido." << endl;
			throw new exception();
		}
	}

	bool CondicionMayorIgual::Analizar(list<Atributo> atributos, list<string> valores){

		typedef list<string>::iterator IteradorDeValores;
		IteradorDeValores IV = valores.begin();

		for ( IteradorDeAtributos i = atributos.begin(); i != atributos.end(); i++){
			Atributo a  = *i;
			// Verifica que el valor no sea nulo, lo cual indica
			// que no se quiere operar sobre el
			if ((*IV).compare("") != 0)
				if (!esMayorIgual(a.Tipo,a.Valor,*IV))
					return false;

			IV++;
		}

		return true;

	}

	bool CondicionMayorIgual::Analizar(Registro registro){

		for ( IteradorDeAtributos i = registro.Atributos.begin(); i != registro.Atributos.end(); i++)
		{
			Atributo a  = *i;
			if ( (a.Nombre.compare(ValorCondicion.Nombre) == 0) && ( a.Tipo == a.Tipo))
				if (!esMayorIgual(a.Tipo,a.Valor,ValorCondicion.Valor))
					return false;
		}

		return true;

	}

	bool CondicionMayorIgual::esMayorIgual(TipoRegistro tipo, string valor1, string valor2){
		short s1, s2, anio1, mes1, dia1, anio2, mes2, dia2;
		int i1, i2;
		float f1, f2;

		switch(tipo)
		{
		case Booleano:
			return true;

		case Cadena:
			return valor1.compare(0,1,valor2) >= 0;

		case Caracter:
			return valor1.compare(valor2)>=0;

		case Entero:
			s1 = (short) atoi(valor1.c_str());
			s2 = (short) atoi(valor2.c_str());

			return s1 >= s2;

		case EnteroLargo:
			i1 = atoi(valor1.c_str());
			i2 = atoi(valor2.c_str());

			return i1 >= i2;

			break;
		case Fecha:
			anio1 = (short) atoi(valor1.substr(6,4).c_str());
			mes1 = (short) atoi(valor1.substr(3,2).c_str());
			dia1 = (short) atoi(valor1.substr(0,2).c_str());

			anio2 = (short) atoi(valor2.substr(6,4).c_str());
			mes2= (short) atoi(valor2.substr(3,2).c_str());
			dia2 = (short) atoi(valor2.substr(0,2).c_str());

			if (anio1>anio2)
				return true;
			else if (anio1 == anio2)
			{
				if (mes1>mes2)
					return true;
				else if ( (mes1== mes2) && (dia1>=dia2) )
					return true;
			}

			return false;

		case Real:
			f1 = (float) atof(valor1.c_str());
			f2 = (float) atof(valor2.c_str());

			return f1>=f2;
		default:
			cerr << "CapaIndices->Condiciones.cpp->CondicionMayorIgual::esMayorIgual(TipoRegistro tipo, string valor1, string valor2)" << endl << "Invalido." << endl;
			throw new exception();
		}

	}

	bool CondicionIgual::Analizar(list<Atributo> atributos, list<string> valores){

		typedef list<string>::iterator IteradorDeValores;
		IteradorDeValores IV = valores.begin();

		for ( IteradorDeAtributos i = atributos.begin(); i != atributos.end(); i++){
			Atributo a  = *i;
			// Verifica que el valor no sea nulo, lo cual indica
			// que no se quiere operar sobre el
			if ((*IV).compare("") != 0)
				if (!esIgual(a.Tipo,a.Valor,*IV))
					return false;

			IV++;
		}

		return true;

	}

	bool CondicionIgual::Analizar(Registro registro){

		for ( IteradorDeAtributos i = registro.Atributos.begin(); i != registro.Atributos.end(); i++)
		{
			Atributo a  = *i;
			if ( (a.Nombre.compare(ValorCondicion.Nombre) == 0) && ( a.Tipo == ValorCondicion.Tipo))
				if (!esIgual(a.Tipo,a.Valor,ValorCondicion.Valor))
					return false;
		}

		return true;

	}

	string Condicion::getSimbolo(){
		switch (Simbolo){
			case Igual:
				return "=";
			case Mayor:
				return ">";
			case MayorIgual:
				return ">=";
			case Menor:
				return "<";
			case MenorIgual:
				return "<=";
			default:
				return " ";
		}
	}

	bool Condicion::esIgual(TipoRegistro tipo, string valor1, string valor2){
		short s1, s2, anio1=0, mes1=0, dia1=0, anio2=0, mes2=0, dia2=0;
		int i1, i2;
		float f1, f2;

		switch(tipo)
		{
		case Booleano:
			return valor1.compare(0,1,valor2) == 0;

		case Cadena:
			return valor1.compare(valor2) == 0;

		case Caracter:
			return valor1.compare(0,1,valor2) == 0;

		case Entero:
			s1 = (short) atoi(valor1.c_str());
			s2 = (short) atoi(valor2.c_str());

			return s1 == s2;

		case EnteroLargo:
			i1 = atoi(valor1.c_str());
			i2 = atoi(valor2.c_str());

			return i1 == i2;

			break;
		case Fecha:
			if (valor1!=""){
				anio1 = (short) atoi(valor1.substr(6,4).c_str());
				mes1 = (short) atoi(valor1.substr(3,2).c_str());
				dia1 = (short) atoi(valor1.substr(0,2).c_str());
			}
			if (valor2!=""){
				anio2 = (short) atoi(valor2.substr(6,4).c_str());
				mes2= (short) atoi(valor2.substr(3,2).c_str());
				dia2 = (short) atoi(valor2.substr(0,2).c_str());
			}
			return ( (anio1==anio2) && (mes1== mes2) && (dia1==dia2) );

		case Real:
			f1 = (float) atof(valor1.c_str());
			f2 = (float) atof(valor2.c_str());

			return f1==f2;
		default:
			cerr << "CapaIndices->Condiciones.cpp->Condicion::esIgual(TipoRegistro tipo, string valor1, string valor2)" << endl << "Invalido." << endl;
			throw new exception();
		}
	}

	CondicionCompuesta::CondicionCompuesta(){
	}

	CondicionCompuesta::~CondicionCompuesta(){

	}


	bool CondicionCompuesta::Analizar(list<Atributo> atributos, list<string> valores)
	{
		typedef list<Condicion*>::iterator LC;
		for (LC i = Subcondiciones.begin(); i!=Subcondiciones.end();i++)
			if (!(*i)->Analizar(atributos,valores))
				return false;

		return true;
	}

	bool CondicionCompuesta::Analizar(Registro registro)
	{
		typedef list<Condicion*>::iterator LC;

		for (LC i = Subcondiciones.begin(); i!=Subcondiciones.end();i++)
			if (!(*i)->Analizar(registro))
				return false;

		return true;
	}

	bool CondicionCompuesta::EsAnd()
	{
		return false;
	}

	bool CondicionCompuestaAND::EsAnd()
	{
		return true;
	}

	bool CondicionCompuestaOR::EsAnd()
	{
		return false;
	}

	bool CondicionCompuestaOR::Analizar(list<Atributo> atributos, list<string> valores)
	{
		typedef list<Condicion*>::iterator LC;
		for (LC i = Subcondiciones.begin(); i!=Subcondiciones.end();i++)
			if ((*i)->Analizar(atributos,valores))
				return true;

		return false;
	}

	bool CondicionCompuestaOR::Analizar(Registro registro)
	{
		typedef list<Condicion*>::iterator LC;

		for (LC i = Subcondiciones.begin(); i!=Subcondiciones.end();i++)
			if ((*i)->Analizar(registro))
				return true;

		return false;
	}



	CondicionCompuestaAND::CondicionCompuestaAND(){
		Simbolo = And;
	}

	CondicionCompuestaAND::~CondicionCompuestaAND(){
	}

	CondicionCompuestaOR::CondicionCompuestaOR(){
		Simbolo = Or;
	}

	CondicionCompuestaOR::~CondicionCompuestaOR(){
	}

}

#endif
